package com.gjxjl.jdbc.gateway.handler;

import com.gjxjl.jdbc.gateway.config.ProxyConfig;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class BinlogSupportHandler extends ChannelInboundHandlerAdapter {
    private static final Logger logger = LogManager.getLogger(BinlogSupportHandler.class);

    private final ProxyConfig config;
    private boolean isBinlogDump = false;
    private long binlogPosition = 0;
    private String binlogFilename = "";

    public BinlogSupportHandler(ProxyConfig config) {
        this.config = config;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof ByteBuf) {
            ByteBuf packet = (ByteBuf) msg;

            // 检查是否是binlog dump请求
            if (isBinlogDumpPacket(packet)) {
                handleBinlogDumpRequest(packet);
                isBinlogDump = true;
                logger.info("Binlog dump request detected - position: {}, file: {}",
                        binlogPosition, binlogFilename);
            }

            // 如果是binlog流量，进行特殊处理
            if (isBinlogDump) {
                handleBinlogTraffic(packet);
            }

            // 继续传递
            ctx.fireChannelRead(msg);
        }
    }

    private boolean isBinlogDumpPacket(ByteBuf packet) {
        if (packet.readableBytes() < 5) {
            return false;
        }

        int readerIndex = packet.readerIndex();
        try {
            // 跳过长度和序列号
            packet.skipBytes(4);
            byte command = packet.readByte();

            // COM_BINLOG_DUMP 命令是 0x12
            return command == 0x12;
        } finally {
            packet.readerIndex(readerIndex);
        }
    }

    private void handleBinlogDumpRequest(ByteBuf packet) {
        int readerIndex = packet.readerIndex();
        try {
            // 跳过包头部
            packet.skipBytes(5);

            // 读取binlog位置
            binlogPosition = packet.readUnsignedIntLE();

            // 读取flags
            packet.skipBytes(2);

            // 读取serverId
            packet.skipBytes(4);

            // 读取binlog文件名
            StringBuilder filename = new StringBuilder();
            byte b;
            while ((b = packet.readByte()) != 0) {
                filename.append((char) b);
            }
            binlogFilename = filename.toString();

            logger.info("Binlog dump request - file: {}, position: {}",
                    binlogFilename, binlogPosition);
        } finally {
            packet.readerIndex(readerIndex);
        }
    }

    private void handleBinlogTraffic(ByteBuf packet) {
        // 对于binlog流量，确保数据完整性
        // 可以在这里添加数据完整性检查

        if (config.isEnableLogging()) {
            logger.debug("Binlog packet - length: {}, position: {}",
                    packet.readableBytes(), binlogPosition);
        }

        // 更新binlog位置（简化处理）
        binlogPosition += packet.readableBytes();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("Binlog handler exception", cause);
        ctx.close();
    }
}
